package priv.pfz.basedao.mybatis.sqlprovider;

import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import priv.pfz.basedao.Utils;
import priv.pfz.basedao.info.DaoInfo;
import priv.pfz.basedao.info.FieldInfo;

import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Map;

/**
 * @author yyjxp
 * 2024/1/28 23:41
 */
public class BaseSqlProvider {

    /**
     * 获取entity对象中非null的字段值
     */
    protected Map<String, Object> getValueMap(DaoInfo daoInfo, Object entity) {
        //若生成了字节码方法，则优先调用字节码方法
        if (daoInfo.getEntityValueMapGetter() != null) {
            try {
                return (Map<String, Object>) daoInfo.getEntityValueMapGetter().invoke(null, entity);
            } catch (InvocationTargetException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }

        //未生成字节码方法，使用反射判断字段是否为空，优先调用getter方法，无getter方法时直接访问field
        Map<String, Object> valueMap = Maps.newHashMap();
        for (FieldInfo fieldInfo : daoInfo.getFieldInfos()) {
            Object value;
            if (fieldInfo.getGetter() != null) {
                value = Utils.getFieldValue(fieldInfo.getGetter(), entity);
            } else {
                value = Utils.getFieldValue(fieldInfo.getField(), entity);
            }
            if (value != null) {
                valueMap.put(fieldInfo.getFieldName(), value);
            }
        }
        return valueMap;
    }

    /**
     * #{xxx}
     */
    protected String getFieldNamePlaceHolder(FieldInfo fieldInfo) {
        return getFieldNamePlaceHolder(null, fieldInfo);
    }

    /**
     * #{xxx}
     * #{arg0.xxx}
     */
    protected String getFieldNamePlaceHolder(String argName, FieldInfo fieldInfo) {
        if (StringUtils.isBlank(argName)) {
            return "#{" + fieldInfo.getFieldName() + "}";
        } else {
            return "#{" + argName + "." + fieldInfo.getFieldName() + "}";
        }
    }

    /**
     * #{arg0[2].xxx}
     */
    protected String getFieldNamePlaceHolder(String argName, int index, FieldInfo fieldInfo) {
        return "#{" + argName + "[" + index + "]." + fieldInfo.getFieldName() + "}";
    }

    /**
     * `xxx` = #{xxx}
     */
    protected String getFieldEquals(FieldInfo fieldInfo) {
        return fieldInfo.getColumnSql() + " = " + getFieldNamePlaceHolder(fieldInfo);
    }

    /**
     * `xxx` = #{arg0.xxx}
     */
    protected String getFieldEquals(String argName, FieldInfo fieldInfo) {
        return fieldInfo.getColumnSql() + " = " + getFieldNamePlaceHolder(argName, fieldInfo);
    }

    /**
     * `xxx` = #{arg0[2].xxx}
     */
    protected String getFieldEquals(String argName, int index, FieldInfo fieldInfo) {
        return fieldInfo.getColumnSql() + " = " + getFieldNamePlaceHolder(argName, index, fieldInfo);
    }

    /**
     * `id` = #{arg0}"
     */
    protected String getIdEquals(String argName) {
        if (StringUtils.isBlank(argName)) {
            return "`id` = #{id}";
        } else {
            return "`id` = #{" + argName + ".id}";
        }
    }

    /**
     * `id` = #{arg0}"
     */
    protected String getIdEqualsArg(String argName) {
        return "`id` = #{" + argName + "}";
    }

    /**
     * `delete_flag` = 0
     */
    protected String getLogicDeleteWhere(DaoInfo daoInfo) {
        return daoInfo.getLogicDeleteColumnSql() + " = 0";
    }

    /**
     * `delete_flag` = `id`
     */
    protected String getLogicDeleteSet(DaoInfo daoInfo) {
        return daoInfo.getLogicDeleteColumnSql() + " = `id`";
    }

    /**
     * `xxx` IN (#{arg0[0]},#{arg0[1]},...)
     */
    protected String getInList(String columnName, String argName, Iterable<?> iterable) {
        StringBuilder sb = new StringBuilder("`").append(columnName).append("` IN (");
        Iterator<?> iterator = iterable.iterator();
        for (int i = 0; iterator.hasNext(); i++) {
            iterator.next();
            sb.append("#{").append(argName).append("[").append(i).append("]}, ");
        }
        return sb.delete(sb.length() - 2, sb.length()).append(")").toString();
    }
}
